﻿using System;

namespace ECommon
{
    /// <summary>
    /// 编号工具
    /// </summary>
    public static class NoTool
    {
        /// <summary>
        /// 创建序列号的时间
        /// </summary>
        private static DateTime _createDate = DateTime.Now;
        /// <summary>
        /// 创建序列号的流水号
        /// </summary>
        private static int _createNo = 0;
        /// <summary>
        /// 创建序列号的两位年号
        /// </summary>
        private static int _year = 0;
        /// <summary>
        /// 创建序列号的年内日期
        /// </summary>
        private static int _day = 0;
        /// <summary>
        /// 创建序列号的天内秒
        /// </summary>
        private static int _second = 0;
        /// <summary>
        /// 源标志字符串的部分散列值移动码
        /// </summary>
        private static int _moveValue = 0;
        /// <summary>
        /// 上次的源标志字符串
        /// </summary>
        private static string _lastFromStr = string.Empty;
        /// <summary>
        /// 源标志字符串的部分散列值
        /// </summary>
        private static string _movePart = string.Empty;
        /// <summary>
        /// 根据源标志以本世纪初为标定时间创建序列号
        /// </summary>
        /// <param name="fromStr">创建序列号的源标志字符串</param>
        /// <returns>创建的序列号</returns>
        /// <exception cref="Exception">序列号编码池耗尽异常</exception>
        public static string Create(string fromStr)
        {
            DateTime current = DateTime.Now;
            _year = current.Year % 100;
            _day = current.DayOfYear;
            _second = current.Hour * 3600 + current.Minute * 60 + current.Second;
            //判定创建序列号的时间是否与上次相同，如果相同，则更新序列号
            if (current.Year == _createDate.Year && current.Month == _createDate.Month && current.Day == _createDate.Day && current.Hour == _createDate.Hour && current.Minute == _createDate.Minute && current.Second == _createDate.Second)
            {
                _createNo++;
            }
            else
            {
                _createNo = 1;
            }
            //根据序列号处理序列号偏移码
            if (_createNo >= 100000000)
            {
                _moveValue++;
                _createNo = 1;
            }
            //如果偏移码过大，则抛出异常
            if (_moveValue >= 22)
            {
                throw new Exception("序列号编码池已耗尽，请稍后重试");
            }
            //处理来源字符串
            if (fromStr != _lastFromStr)
            {
                _movePart = Md5Tool.GetMd5ByString(fromStr).Substring(_moveValue, 10);
                _lastFromStr = fromStr;
            }
            //将时间赋值给创建的时间
            _createDate = current;
            return _year.ToString().PadLeft(2, '0')+_day.ToString().PadLeft(3, '0')+_moveValue.ToString().PadLeft(2, '0')+ _movePart + _createNo.ToString().PadLeft(8, '0')+_second.ToString().PadLeft(5, '0');
        }
    }
}
